#include "ConcreteObserverExample.h"

void ConcreteObservable::setProp1(bool prop1)
{
    // Cambiamos el valor de la primer propiedad.
    _prop1 = prop1;

    // Se lo indicamos a los observadores.
    this->notify(
                UpdateInfo(
                     ConcreteUpdateInfo::Prop1Changed));
}

bool ConcreteObservable::prop1() const
{
    return _prop1;
}

void ConcreteObservable::setProp2(bool prop2)
{
    // Cambiamos el valor de la segunda propiedad.
    _prop2 = prop2;

    // Le indicamos a los observadores que la segunda
    // propiedad cambio y cual es su nuevo valor.
    this->notify(
                ConcreteChanged(
                    _prop2,
                    ConcreteUpdateInfo::Prop2Changed));
}

bool ConcreteObservable::prop2() const
{
    return _prop2;
}

ConcreteChanged::ConcreteChanged(bool prop2Value, int type)
    : UpdateInfo(type), _prop2(prop2Value)
{
}

bool ConcreteChanged::prop2() const
{
    return _prop2;
}

void ConcreteObserver::update(Observable *observable,
                              const UpdateInfo &info)
{
    /// Actualizamos nuestras propiedades con
    /// respecto a los cambios del objeto observado.
    /// Para simular un verdadero ejemplo
    /// cabiamos los valores de bool a string.
    // Creamos una funcion para pasar de bool a string.
    auto boolToString =
            [] (bool b) -> std::string {
        return (b == true)? "true" : "false";
    };

    // Verificamos cual fue la propiedad que cambio.
    if (info.type() == ConcreteUpdateInfo::Prop1Changed) {
        // Hacemos downcasting del objeto observado
        // para obtener el nuevo valor de la propiedad.
        ConcreteObservable *concreteObservable =
                static_cast<ConcreteObservable *>(observable);

        // Actualizamos nuestra propiedad.
        _prop1 = boolToString(concreteObservable->prop1());
    }
    else if (info.type() == ConcreteUpdateInfo::Prop2Changed) {
        // Hacemos downcasting de la informacion
        // para obtener el nuevo valor de la propiedad.
        const ConcreteChanged &concreteInfo =
                static_cast<const ConcreteChanged &>(info);

        // Actualizamos nuestra propiedad.
        _prop2 = boolToString(concreteInfo.prop2());
    }
}

std::string ConcreteObserver::prop1() const
{
    return _prop1;
}

std::string ConcreteObserver::prop2() const
{
    return _prop2;
}
